#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "nvs_flash.h"
#include <stdio.h>
#include "DEV_Config.h"
#include "EPD_4in2.h"
#include "GUI_Paint.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "esp_netif.h"
#include "lwip/err.h"
#include "lwip/sys.h"
#include "esp_tls.h"
#include "esp_http_client.h"
#include <inttypes.h>
#include "cJSON.h"
#include "icons.h"
#include "jpg.h"
#include "lwip/apps/sntp.h"

/* WiFi配置 */
#define WiFi_STA_SSID "Tenda_16F4C0"
#define WiFi_STA_PASSWORD "804804qwe"
#define WiFi_MAX_RETRY 15

/* 全局变量 */
static EventGroupHandle_t wifi_event_group;
#define WIFI_CONNECTED_BIT BIT0
#define WIFI_FAIL_BIT      BIT1
static const char *TAG = "Main";
char Time_Buff[16] = {0};
char Temp_Buff[16] = {0};
char Hum_Buff[16] = {0};
UBYTE *BlackImage = NULL;

/* 函数声明 */
void update_display(void);
void fetch_weather_data(void);
void initialize_sntp(void);
void obtain_time(void);
void time_sync_notification_cb(struct timeval *tv);

/* NTP配置 */
#define NTP_SERVER "pool.ntp.org"
#define TIME_ZONE 8  // 东八区

void initialize_sntp(void)
{
    ESP_LOGI(TAG, "Initializing SNTP");
    sntp_setoperatingmode(SNTP_OPMODE_POLL);
    sntp_setservername(0, NTP_SERVER);
    time_sync_notification_cb(time_sync_notification_cb);
    sntp_init();
}

void obtain_time(void)
{
    initialize_sntp();
    time_t now = 0;
    struct tm timeinfo = {0};
    int retry = 0;
    const int retry_count = 15;
    
    while (timeinfo.tm_year < (2024 - 1900) && ++retry < retry_count) {
        ESP_LOGI(TAG, "Waiting for system time to be set... (%d/%d)", retry, retry_count);
        vTaskDelay(2000 / portTICK_PERIOD_MS);
        time(&now);
        localtime_r(&now, &timeinfo);
    }
    
    setenv("TZ", "CST-8", 1);  // 设置时区为东八区
    tzset();
}

void time_sync_notification_cb(struct timeval *tv)
{
    ESP_LOGI(TAG, "Time synchronized");
}

void update_time_string()
{
    time_t now;
    struct tm timeinfo;
    time(&now);
    localtime_r(&now, &timeinfo);
    strftime(Time_Buff, sizeof(Time_Buff), "%H:%M", &timeinfo);
}

/* HTTP请求处理 */
static void http_client_task(void *pvParameters)
{
    char output_buffer[2000] = {0};
    static const char *URL = "http://api.seniverse.com/v3/weather/daily.json?"
                             "key=Sghh4k6zfmsId_xYm&location=hangzhou"
                             "&language=en&unit=c&start=0&days=7";

    esp_http_client_config_t config = { .url = URL };
    esp_http_client_handle_t client = esp_http_client_init(&config);

    esp_http_client_set_method(client, HTTP_METHOD_GET);
    esp_err_t err = esp_http_client_open(client, 0);
    
    if (err == ESP_OK) {
        int content_length = esp_http_client_fetch_headers(client);
        if (content_length > 0) {
            esp_http_client_read_response(client, output_buffer, sizeof(output_buffer));
            cJSON *root = cJSON_Parse(output_buffer);
            if (root) {
                cJSON *results = cJSON_GetObjectItem(root, "results");
                if (results) {
                    cJSON *daily = cJSON_GetObjectItem(cJSON_GetArrayItem(results, 0), "daily");
                    if (daily) {
                        cJSON *today = cJSON_GetArrayItem(daily, 0);
                        if (today) {
                            cJSON *low = cJSON_GetObjectItem(today, "low");
                            cJSON *high = cJSON_GetObjectItem(today, "high");
                            cJSON *humidity = cJSON_GetObjectItem(today, "humidity");
                            if (low && high && humidity) {
                                snprintf(Temp_Buff, sizeof(Temp_Buff), "%s~%sC", 
                                         low->valuestring, 
                                         high->valuestring);
                                snprintf(Hum_Buff, sizeof(Hum_Buff), "Humi:%s%%", 
                                         humidity->valuestring);
                            }
                        }
                    }
                }
                cJSON_Delete(root);
            }
        }
    }
    esp_http_client_close(client);
    vTaskDelete(NULL);
}

/* WiFi事件处理 */
static void wifi_event_handler(void* arg, esp_event_base_t event_base,
                              int32_t event_id, void* event_data)
{
    static uint8_t retry_count = 0;
    if (event_base == WIFI_EVENT) {
        if (event_id == WIFI_EVENT_STA_START) {
            esp_wifi_connect();
        } else if (event_id == WIFI_EVENT_STA_DISCONNECTED) {
            if (retry_count++ < WiFi_MAX_RETRY) {
                esp_wifi_connect();
            } else {
                xEventGroupSetBits(wifi_event_group, WIFI_FAIL_BIT);
            }
        }
    } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
        retry_count = 0;
        xEventGroupSetBits(wifi_event_group, WIFI_CONNECTED_BIT);
        obtain_time();
        xTaskCreate(http_client_task, "http_task", 4096, NULL, 5, NULL);
    }
}

void wifi_init_sta(void)
{
    wifi_event_group = xEventGroupCreate();
    ESP_ERROR_CHECK(esp_netif_init());
    ESP_ERROR_CHECK(esp_event_loop_create_default());
    esp_netif_create_default_wifi_sta();

    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK(esp_wifi_init(&cfg));

    ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, NULL));
    ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &wifi_event_handler, NULL));

    wifi_config_t wifi_config = {
        .sta = {
            .ssid = WiFi_STA_SSID,
            .password = WiFi_STA_PASSWORD,
        },
    };
    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
    ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config));
    ESP_ERROR_CHECK(esp_wifi_start());
}

/* EPD显示函数 */
void update_display(void)
{
    Paint_Clear(WHITE);
    
    // 绘制时间
    update_time_string();
    Paint_DrawString_EN(50, 40, Time_Buff, &Font24, WHITE, BLACK);
    
    // 绘制天气信息
    Paint_DrawImage(image_data_daysunny, 50, 85, 40, 40);
    Paint_DrawString_EN(91, 90, Temp_Buff, &Font16, WHITE, BLACK);
    Paint_DrawString_EN(91, 110, Hum_Buff, &Font16, WHITE, BLACK);
    
    // 更新屏幕
    EPD_4IN2_Display(BlackImage);
    EPD_4IN2_Sleep();  // 进入睡眠节省功耗
}

/* 主任务 */
void main_task(void *pvParameters)
{
    // 初始化EPD
    DEV_Gpio_Init();
    EPD_4IN2_Init_Fast();
    EPD_4IN2_Clear();
    
    // 创建图像缓存
    UWORD image_size = ((EPD_4IN2_WIDTH % 8 == 0) ? (EPD_4IN2_WIDTH / 8) : (EPD_4IN2_WIDTH / 8 + 1)) * EPD_4IN2_HEIGHT;
    BlackImage = (UBYTE *)malloc(image_size);
    Paint_NewImage(BlackImage, EPD_4IN2_WIDTH, EPD_4IN2_HEIGHT, 0, WHITE);
    
    while(1) {
        update_display();
        EPD_4IN2_Init_Fast();  // 唤醒屏幕
        vTaskDelay(pdMS_TO_TICKS(60000));  // 60秒刷新间隔
    }
}

void app_main(void)
{
    ESP_ERROR_CHECK(nvs_flash_init());
    wifi_init_sta();
    
    // 等待WiFi连接
    EventBits_t bits = xEventGroupWaitBits(wifi_event_group,
                                          WIFI_CONNECTED_BIT | WIFI_FAIL_BIT,
                                          pdFALSE, pdFALSE, portMAX_DELAY);
                                          
    if (bits & WIFI_CONNECTED_BIT) {
        xTaskCreate(main_task, "main_task", 4096, NULL, 5, NULL);
    } else {
        ESP_LOGE(TAG, "Failed to connect to WiFi");
    }
}